package com.tsfyun.scm.base;

import cn.hutool.core.collection.CollUtil;
import com.google.common.collect.Lists;
import com.tsfyun.common.base.dto.Result;
import com.tsfyun.common.base.dto.WriteOffOrderCostDTO;
import com.tsfyun.common.base.enums.BizParamEnum;
import com.tsfyun.common.base.enums.BusinessTypeEnum;
import com.tsfyun.common.base.exception.ServiceException;
import com.tsfyun.common.base.util.LocalDateTimeUtils;
import com.tsfyun.common.base.util.TsfPreconditions;
import com.tsfyun.scm.base.entity.OperationMaintenance;
import com.tsfyun.scm.client.BaseDataClient;
import com.tsfyun.scm.client.CustomsCodeClient;
import com.tsfyun.scm.client.DeclareServerClient;
import com.tsfyun.scm.service.system.ISysParamService;
import com.tsfyun.scm.system.vo.CustomsCodeVO;
import com.tsfyun.scm.system.vo.CustomsElementsVO;
import com.tsfyun.scm.vo.system.SysParamVO;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

/**=
 * 基础数据调用
 */
public class DataCalling {

    private static BaseDataClient baseDataClient;
    public void setBaseDataClient(BaseDataClient baseDataClient){
        this.baseDataClient = baseDataClient;
    }

    /**=
     * 获取海关汇率
     * @param currencyId
     * @param dateTime
     * @return
     */
    public static BigDecimal obtainCustomsRate(String currencyId, LocalDateTime dateTime){
        return obtainCustomsRate(currencyId,LocalDateTimeUtils.convertLDTToDate(dateTime));
    }
    public static BigDecimal obtainCustomsRate(String currencyId, Date date){
        if("CNY".equals(currencyId)){
            return BigDecimal.ONE;
        }
        Result<BigDecimal> result = baseDataClient.obtainCustomsRate(currencyId,date);
        if(result.isSuccess()){
            return result.getData();
        }
        return null;
    }
    //美金金额转换
    public static BigDecimal convertUSDAmount(LocalDateTime dateTime,String currencyId,BigDecimal totalPrice){
        return convertUSDAmount(LocalDateTimeUtils.convertLDTToDate(dateTime),currencyId,totalPrice);
    }
    //美金金额转换
    public static BigDecimal convertUSDAmount(Date date,String currencyId,BigDecimal totalPrice){
        if("USD".equals(currencyId)){return totalPrice;}
        BigDecimal CNYPrice = totalPrice;//人民币金额
        if(!"CNY".equals(currencyId)) {//不是人民币转人民币
            CNYPrice = totalPrice.multiply(obtainCustomsRate(currencyId,date));
        }
        //人民币转美金
        return CNYPrice.divide(obtainCustomsRate("USD",date),2,BigDecimal.ROUND_HALF_UP);
    }
    //获取中行汇率
    public static BigDecimal obtainBankChinaRate(String currencyId,String rateType, String date){
        if("CNY".equals(currencyId)){
            return BigDecimal.ONE;
        }
        Result<BigDecimal> result = baseDataClient.obtainBankChinaRate(currencyId,rateType,date);
        if(Objects.nonNull(result) && result.isSuccess()){
            return result.getData();
        }
        return null;
    }
    //获取税点
    public static BigDecimal obtainTaxPoint(BusinessTypeEnum businessType){
        switch (businessType){
            case IMP_AGENT://代理进口
                return BigDecimal.valueOf(0.06);
            case IMP_COOPERATE://自营进口
                return BigDecimal.valueOf(0.13);
        }
        return null;
    }

    private static ISysParamService sysParamService;
    public void setSysParamService(ISysParamService sysParamService){
        this.sysParamService = sysParamService;
    }
    //获取进口CIF运保费率
    public static BigDecimal impCIFRate(){
        SysParamVO sysParam = getSysParamVOById(BizParamEnum.IMPCIF.getCode());
        TsfPreconditions.checkArgument(Objects.nonNull(sysParam),new ServiceException("成交方式CIF运保费率未配置，请先配置。"));
        TsfPreconditions.checkArgument(!Objects.equals(Boolean.TRUE,sysParam.getDisabled()),new ServiceException("成交方式CIF运保费率已被禁用，请先开启。"));
        return new BigDecimal(sysParam.getVal());
    }

    public static SysParamVO getSysParamVOById(String id){
        Map<String,SysParamVO> map = sysParamService.obtainAllParamMap();
        SysParamVO sysParamVO = null;
        if(Objects.nonNull(map)){
            sysParamVO = map.get(id);
        }
        if(Objects.isNull(sysParamVO)){
            sysParamVO = sysParamService.getById(id);
        }
        return sysParamVO;
    }

    //获取运保杂费率
    public static List<OperationMaintenance> impFOBRate(){
        List<String> stringList = impFOBRateStr();
        return formatImpFOBRateStr(stringList);
    }
    public static List<OperationMaintenance> formatImpFOBRateStr(List<String> stringList){
        List<OperationMaintenance> ims = Lists.newArrayList();
        stringList.stream().forEach(str ->{
            List<String> vals = Arrays.asList(str.split("/"));
            OperationMaintenance im = new OperationMaintenance();
            im.setCurrency(vals.get(0));
            im.setVal(new BigDecimal(vals.get(1)));
            im.setType(Integer.parseInt(vals.get(2)));
            ims.add(im);
        });
        return ims;
    }
    //获取运保杂费率
    public static List<String> impFOBRateStr(){
        SysParamVO sysParam = getSysParamVOById(BizParamEnum.IMPFOB.getCode());
        TsfPreconditions.checkArgument(Objects.nonNull(sysParam),new ServiceException("成交方式FOB运保费率未配置，请先配置。"));
        TsfPreconditions.checkArgument(!Objects.equals(Boolean.TRUE,sysParam.getDisabled()),new ServiceException("成交方式FOB运保费率已被禁用，请先开启。"));
        List<String> stringList = Arrays.asList(sysParam.getVal().split(","));
        return stringList;
    }

    //海关编码数据
    private static CustomsCodeClient customsCodeClient;
    public void setCustomsCodeClient(CustomsCodeClient customsCodeClient){
        this.customsCodeClient = customsCodeClient;
    }
    //根据海关编码获取详情
    public static CustomsCodeVO obtainHsCodeDetail(String hsCode){
        Result<CustomsCodeVO> result = customsCodeClient.detail(hsCode);
        TsfPreconditions.checkArgument(result.isSuccess(),new ServiceException(result.getMessage()));
        return result.getData();
    }
    //根据海关编码获取申报要素
    public static List<CustomsElementsVO> obtainCustomsElements(String hsCode){
        Result<List<CustomsElementsVO>> result = customsCodeClient.elementDetail(hsCode);
        TsfPreconditions.checkArgument(result.isSuccess(),new ServiceException(result.getMessage()));
        return result.getData();
    }

    private static DeclareServerClient declareServerClient;
    public void setDeclareServerClient(DeclareServerClient declareServerClient){
        this.declareServerClient = declareServerClient;
    }

    // 取消费用核销
    public static void cancelwriteOffByCosts(List<WriteOffOrderCostDTO> costs){
        if(CollUtil.isEmpty(costs)){
            return;
        }
        Result result = declareServerClient.cancelwriteOffByCosts(costs);
        if(Objects.isNull(result) || !result.isSuccess()){
            throw new ServiceException("取消费用核销拥堵，请稍后重试");
        }
    }


    private static DataCalling instance;

    private DataCalling() {

    }

    public static DataCalling getInstance() {
        if (instance == null) {
            synchronized (DataCalling.class) {
                if (instance == null) {
                    instance = new DataCalling();
                }
            }
        }
        return instance;
    }

}
